#ifndef RSA_H
#define RSA_H

#include <gmp.h>
#include <sstream>

#include "signature_manager.h"
#include "GMPInt.h"


struct RSA_privatekey {
    GMPInt d; // 私有指数
    GMPInt n; // 模数


    RSA_privatekey() = default;
    RSA_privatekey(const mpz_t& d, const mpz_t& n) : d(d), n(n) {}

    void set_by_str(const std::string& str){
        std::istringstream ss{str};
        std::string item;
        std::getline(ss, item, ',');
        mpz_set_str(d, item.c_str(), 10);

        std::getline(ss, item, ','); 
        mpz_set_str(n, item.c_str(), 10);
    }

    std::string to_str() const {
        char* str1 = mpz_get_str(nullptr, 10, d);
        std::string result(str1);
        free(str1);
        char* str2 = mpz_get_str(nullptr, 10, n);
        result += "," + std::string(str2);
        free(str2);
        return result;
    }
};

struct RSA_publickey {
    GMPInt e; // 公共指数
    GMPInt n; // 模数


    RSA_publickey(){
        #ifdef DEBUG_PRINTS_LEVEL_3
    std::cout << "RSA_publickey constructor called" << std::endl;
#endif
    }
    RSA_publickey(const mpz_t& e, const mpz_t& n) : e(e), n(n) {}

    void set_by_str(const std::string& str){
        std::istringstream ss{str};
        std::string item;
        std::getline(ss, item, ',');
            mpz_set_str(e, item.c_str(), 10);

        std::getline(ss, item, ','); 
            mpz_set_str(n, item.c_str(), 10);
    }

    std::string to_str() const {
        char* str1 = mpz_get_str(nullptr, 10, e);
        std::string result(str1);
        free(str1);
        char* str2 = mpz_get_str(nullptr, 10, n);
        result += "," + std::string(str2);
        free(str2);
        return result;
    }
};

struct RSA_publicparameter{
    bool is_valid = true;

    std::string to_str(){
        return "";
    }

    void set_by_str(const std::string& str){
        is_valid = true;
    }
};

struct RSA_signature {
    GMPInt s; // 签名值

    RSA_signature() = default;
    RSA_signature(const mpz_t& s) : s(s) {}
    RSA_signature(const std::string& str){
        mpz_set_str(s, str.c_str(), 10);
    }
    std::string to_str() const {
        char* str = mpz_get_str(nullptr, 10, s);
        std::string result(str);
        free(str);
        return result;
    }
    void set_by_str(const std::string& str) {
        mpz_set_str(s, str.c_str(), 10);
    }
};

template<int key_length>
class RSA : public SignatureAlgorithm<RSA_privatekey, RSA_publickey,RSA_publicparameter, RSA_signature> {
public:

    void generatepublicparameters(RSA_publicparameter& publicParameters) override{}

    /*
    RSA 密钥对生成
    */
    void generateKeyPair(RSA_privatekey &private_key, RSA_publickey &public_key, RSA_publicparameter &publicParameters) override;

    /*
    RSA 签名算法实现：使用传入的私钥对消息进行签名，并返回签名结果
    */
    RSA_signature sign(const PlainMessage &message, const RSA_privatekey &private_key, const RSA_publicparameter &publicParameters) override; 

    /*
    RSA 验证算法实现：使用传入的公钥验证消息的签名是否有效
    */
    bool verify(const PlainMessage &message, const RSA_publickey &public_key, const RSA_publicparameter &publicParameters, const RSA_signature &signature) override;
};

template<int key_length>
struct RSA_type_traits{
    using algo = RSA<key_length>;
    using private_key = RSA_privatekey;
    using public_key = RSA_publickey;
    using params = RSA_publicparameter;
    using signature = RSA_signature;
};

extern template class RSA<1024>;
extern template class RSA<2048>;
extern template class RSA<3072>;



#endif // RSA_H
